from enum import StrEnum
import logging
from sqlalchemy import func
from sqlalchemy.ext.mutable import MutableDict
from models.engine import db
from models.robot.rob_charater import RobCharacter
from models.robot.rob_domain import RobFunDomain
from models.types import StringUUID
from sqlalchemy.dialects.postgresql import JSONB


class AgentType(StrEnum):
    Agent = "agent"
    FlowPot = "flow_pot"

    @staticmethod
    def choices():
        return ["agent", "flow_pot"]


class RobotExtraInfo(db.Model):
    __tablename__ = "rob_extra_info"
    __table_args__ = (
        db.PrimaryKeyConstraint('id', name='rob_extra_pk'),
        db.Index('idx_rob_extra_account_id', 'account_id'),
    )
    id = db.Column(db.String(64), primary_key=True)
    tenant_id = db.Column(StringUUID, nullable=False)
    account_id = db.Column(StringUUID, nullable=False)
    robot_name = db.Column(db.String(128),nullable=True,comment="精灵名称")
    user_name = db.Column(db.String(128), nullable=True, comment="用户名")
    phone = db.Column(db.String(32), nullable=True, comment="手机号")
    postal_code = db.Column(db.BigInteger(), nullable=True, comment="邮编")
    extra_info = db.Column(MutableDict.as_mutable(
        JSONB), default={}, comment="扩展信息")
    last_ip = db.Column(db.String(32), nullable=True, comment="最后登录ip")
    last_login_at = db.Column(db.DateTime, nullable=True, comment="最后登录时间")

    @property
    def robot(self) -> "Robots|None":
        return db.session.get(Robots, self.id)

    @property
    def district(self) -> str:
        try:
            from models.robot.area_code import SystemAreaCode
            area = db.session.query(SystemAreaCode).filter(
                SystemAreaCode.code == self.postal_code*1000000).first()
            if area:
                return area.distrct_str
        except Exception as e:
            logging.error(e, stack_info=True)

        return ""


class Robots(db.Model):
    __tablename__ = "robots"
    __table_args__ = (
        db.PrimaryKeyConstraint("id", name="robots_pkey"),
        db.Index("idx_robots_activated_at", "activated_at"),
    )
    id = db.Column(db.String(64), primary_key=True)
    tenant_id = db.Column(StringUUID, nullable=False)
    bluetooth_id = db.Column(db.String(128),nullable=True,comment="蓝牙id")
    h_version = db.Column(db.String(32), nullable=True, comment="硬件版本")
    f_version = db.Column(db.String(32), nullable=True, comment="固件版本")
    activated_at = db.Column(db.DateTime, nullable=True, comment="激活时间")
    agent_type = db.Column(db.String(16), nullable=False, comment="设备类型")
    fun_domain_id = db.Column(StringUUID, nullable=False, comment="功能域")
    cur_charater_id = db.Column(StringUUID, nullable=False, comment="当前角色")
    cur_timbre_id = db.Column(StringUUID, nullable=False, comment="当前声调")
    cur_emoji_pack_id = db.Column(StringUUID, nullable=False, comment="当前表情包")
    extra_funcs = db.Column(MutableDict.as_mutable(
        JSONB), nullable=True, default={}, comment="额外功能")
    extra_timbres = db.Column(MutableDict.as_mutable(
        JSONB), nullable=True, default={}, comment="额外声调")
    extra_emoji_packs = db.Column(MutableDict.as_mutable(
        JSONB), nullable=True, default={}, comment="额外表情包")
    chat_language = db.Column(
        db.String(16), nullable=False, server_default=db.text('zh'), comment="聊天语言")
    created_at = db.Column(db.DateTime, nullable=False,
                           server_default=func.current_timestamp(), comment="创建时间")
    updated_at = db.Column(db.DateTime, nullable=True,
                           server_default=func.current_timestamp(), comment="更新时间")
    created_by = db.Column(StringUUID, nullable=False, comment="创建人")
    updated_by = db.Column(StringUUID, nullable=True, comment="更新人")

    @property
    def extra_info(self) -> RobotExtraInfo | None:
        return db.session.get(RobotExtraInfo, self.id)

    @property
    def fun_domain(self) -> RobFunDomain | None:
        if not self.fun_domain_id:
            return None
        return db.session.get(RobFunDomain, self.fun_domain_id)

    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "h_version": self.h_version,
            "f_version": self.f_version,
            "activated_at": self.activated_at.timestamp() if self.activated_at else None,
            "agent_type": self.agent_type,
            "extra_funcs": self.extra_funcs,
            "extra_emojis": self.extra_emoji_packs,
            "extra_timbres": self.extra_timbres,
        }

    @property
    def characters(self) -> list[RobCharacter]:
        try:
            return db.session.query(RobCharacter).join(RobotCharacterMap, RobotCharacterMap.character_id == RobCharacter.id).filter(RobotCharacterMap.robot_id == self.id).all()
        except:
            return []
        
    


class RobotCharacterMap(db.Model):
    __tablename__ = "rob_character_map"
    __table_args__ = (
        db.PrimaryKeyConstraint(
            "robot_id", "character_id", name="rob_character_map_pkey"),
        db.Index("rob_character_map_robot", "robot_id"),
    )
    robot_id = db.Column(db.String(64), nullable=False)
    character_id = db.Column(StringUUID, nullable=False)
